from flask import Blueprint, render_template, request, redirect, url_for, session, flash, jsonify, make_response
from models import UserModel, CardModel, db, TradeModel, DepositModel
from sqlalchemy import or_, func, and_
import csv
from io import StringIO
import random
from datetime import datetime

admincard_dp = Blueprint('admincard', __name__, url_prefix='/admincard')


# 生成随机银行卡号
def generate_card_id():
    while True:
        card_id = '62' + ''.join(str(random.randint(0, 9)) for _ in range(14))
        if not CardModel.query.filter_by(cardID=card_id).first():
            return card_id


@admincard_dp.route('/admincardmain', methods=['GET', 'POST'])
def admincardmain():
    # 处理搜索
    card_id = request.args.get('cardIdSearch', '').strip()
    customer_id = request.args.get('customerIdSearch', '').strip()
    page = request.args.get('page', 1, type=int)
    per_page = 10

    # 构建查询 - 连接deposit表获取存款类型名称
    query = db.session.query(
        CardModel,
        func.coalesce(DepositModel.savingName, '无').label('saving_name')
    ).outerjoin(DepositModel, CardModel.savingID == DepositModel.savingID)

    if card_id:
        query = query.filter(CardModel.cardID.like(f'%{card_id}%'))
    if customer_id:
        query = query.filter(CardModel.customerID == customer_id)

    # 执行分页查询
    pagination = query.paginate(page=page, per_page=per_page, error_out=False)

    # 重构结果以便模板使用
    cards_with_saving = []
    for card, saving_name in pagination.items:
        card.saving_name = saving_name
        cards_with_saving.append(card)

    # 创建自定义分页对象
    class CustomPagination:
        def __init__(self, items, page, per_page, total, pages):
            self.items = items
            self.page = page
            self.per_page = per_page
            self.total = total
            self.pages = pages
            self.has_prev = page > 1
            self.has_next = page < pages
            self.prev_num = page - 1 if page > 1 else None
            self.next_num = page + 1 if page < pages else None

    custom_pagination = CustomPagination(
        items=cards_with_saving,
        page=page,
        per_page=per_page,
        total=pagination.total,
        pages=pagination.pages
    )

    return render_template("admin_main_card.html",
                           cards=custom_pagination,
                           cardIdSearch=card_id,
                           customerIdSearch=customer_id)


@admincard_dp.route('/add_card', methods=['POST'])
def add_card():
    try:
        # 获取表单数据
        saving_id = request.form.get('savingID')
        open_money = float(request.form.get('openMoney'))
        customer_id = int(request.form.get('customerID'))

        # 创建新银行卡 (币种默认为RMB)
        new_card = CardModel(
            cardID=generate_card_id(),
            curID='RMB',  # 默认币种为RMB
            savingID=saving_id,
            openDate=datetime.now(),
            openMoney=open_money,
            balance=open_money,
            passwd='123456',  # 默认密码
            IsReportLoss='否',
            customerID=customer_id
        )

        db.session.add(new_card)
        db.session.commit()
        flash('银行卡添加成功!', 'success')
    except Exception as e:
        db.session.rollback()
        flash(f'添加银行卡失败: {str(e)}', 'danger')

    return redirect(url_for('admincard.admincardmain'))


@admincard_dp.route('/edit_card', methods=['POST'])
def edit_card():
    try:
        card_id = request.form.get('cardId')
        card = CardModel.query.get(card_id)

        if card:
            card.savingID = request.form.get('savingID')
            card.openMoney = float(request.form.get('openMoney'))
            card.balance = float(request.form.get('balance'))
            card.IsReportLoss = request.form.get('IsReportLoss')
            card.customerID = int(request.form.get('customerID'))

            db.session.commit()
            flash('银行卡信息更新成功!', 'success')
        else:
            flash('银行卡不存在!', 'danger')
    except Exception as e:
        db.session.rollback()
        flash(f'更新银行卡信息失败: {str(e)}', 'danger')

    return redirect(url_for('admincard.admincardmain'))


@admincard_dp.route('/delete_card/<card_id>', methods=['POST'])
def delete_card(card_id):
    try:
        card = CardModel.query.get(card_id)

        if card:
            # 检查是否有交易记录
            has_trades = TradeModel.query.filter_by(cardID=card_id).first()
            if has_trades:
                flash('无法删除有交易记录的银行卡!', 'danger')
            else:
                db.session.delete(card)
                db.session.commit()
                flash('银行卡删除成功!', 'success')
        else:
            flash('银行卡不存在!', 'danger')
    except Exception as e:
        db.session.rollback()
        flash(f'删除银行卡失败: {str(e)}', 'danger')

    return redirect(url_for('admincard.admincardmain'))


@admincard_dp.route('/export_cards_csv')
def export_cards_csv():
    # 获取搜索参数
    card_id = request.args.get('cardIdSearch', '').strip()
    customer_id = request.args.get('customerIdSearch', '').strip()

    # 构建查询 - 连接deposit表
    query = db.session.query(
        CardModel,
        func.coalesce(DepositModel.savingName, '无').label('saving_name')
    ).outerjoin(DepositModel, CardModel.savingID == DepositModel.savingID)

    if card_id:
        query = query.filter(CardModel.cardID.like(f'%{card_id}%'))
    if customer_id:
        query = query.filter(CardModel.customerID == customer_id)

    # 获取所有符合条件的银行卡
    cards = query.all()

    # 创建CSV输出
    si = StringIO()
    cw = csv.writer(si)

    # 写入表头
    cw.writerow(['卡号', '币种', '存款类型', '开户日期', '开户金额', '余额', '密码', '是否挂失', '客户编号'])

    # 写入数据
    for card, saving_name in cards:
        cw.writerow([
            card.cardID,
            card.curID,
            saving_name,
            card.openDate.strftime('%Y-%m-%d %H:%M:%S'),
            card.openMoney,
            card.balance,
            card.passwd,
            card.IsReportLoss,
            card.customerID
        ])

    # 创建响应
    output = make_response(si.getvalue())
    output.headers["Content-Disposition"] = "attachment; filename=bank_cards.csv"
    output.headers["Content-type"] = "text/csv"
    return output


@admincard_dp.route('/card_detail/<card_id>')
def card_detail(card_id):
    try:
        # 获取银行卡信息 - 连接deposit表
        card_data = db.session.query(
            CardModel,
            func.coalesce(DepositModel.savingName, '无').label('saving_name'),
            UserModel.customerName
        ).outerjoin(DepositModel, CardModel.savingID == DepositModel.savingID) \
            .outerjoin(UserModel, CardModel.customerID == UserModel.customerID) \
            .filter(CardModel.cardID == card_id) \
            .first()

        if not card_data:
            return jsonify({'error': '银行卡不存在'}), 404

        card, saving_name, customer_name = card_data

        # 获取最近5笔交易记录
        transactions = TradeModel.query.filter_by(cardID=card_id) \
            .order_by(TradeModel.tradeDate.desc()) \
            .limit(5) \
            .all()

        # 准备响应数据
        card_data = {
            'cardID': card.cardID,
            'curID': card.curID,
            'savingID': saving_name,  # 存款类型名称
            'openDate': card.openDate.strftime('%Y-%m-%d'),
            'openMoney': float(card.openMoney),
            'balance': float(card.balance),
            'IsReportLoss': card.IsReportLoss,
            'customerID': card.customerID,
            'customerName': customer_name if customer_name else '未知客户',
            'transactions': [
                {
                    'tradeDate': t.tradeDate.strftime('%Y-%m-%d %H:%M'),
                    'tradeType': t.tradeType,
                    'tradeMoney': float(t.tradeMoney),
                    'remark': t.remark
                } for t in transactions
            ]
        }

        return jsonify(card_data)
    except Exception as e:
        return jsonify({'error': str(e)}), 500


# 获取所有存款类型
@admincard_dp.route('/get_deposit_types')
def get_deposit_types():
    try:
        deposit_types = DepositModel.query.all()
        return jsonify([{'savingID': dt.savingID, 'savingName': dt.savingName} for dt in deposit_types])
    except Exception as e:
        return jsonify({'error': str(e)}), 500


# 重置密码
@admincard_dp.route('/reset_password', methods=['POST'])
def reset_password():
    try:
        data = request.json
        card_id = data.get('cardId')
        new_password = data.get('newPassword')

        card = CardModel.query.get(card_id)
        if not card:
            return jsonify({'error': '银行卡不存在'}), 404

        card.passwd = new_password
        db.session.commit()
        return jsonify({'message': '密码重置成功!'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500